using System;
using System.Reflection;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml;
using System.Collections;
using SharpObjects.Configuration;
using SharpObjects.Configuration.ConfigurationProviders;
using System.Web;
using SharpObjects.Interfaces;

namespace SharpObjects.Logging.LogTargets 
{
	public class BinaryFileLogTarget : FileLogTargetBase
	{
        protected static BinaryFormatter binaryFormatter = new BinaryFormatter();

        public static void Save(object obj, Stream stream)
        {
            binaryFormatter.Serialize(stream, obj);
        }

		protected FileStream fileStream = null;

        #region CONSTRUCTORS

        public BinaryFileLogTarget()
		{
		}

		public BinaryFileLogTarget(string logDirectory)
            : base(logDirectory)
        {
		}

		public BinaryFileLogTarget(string logDirectory, string logFileNameBase)
            : base(logDirectory, logFileNameBase)
		{
		}

		public BinaryFileLogTarget(string logDirectory, string logFileNameBase, string extension)
            : base(logDirectory, logFileNameBase, extension)
        {
		}

		public BinaryFileLogTarget(string logDirectory, string logFileNameBase, string extension, int maxSize)
		    : base(logDirectory, logFileNameBase, extension, maxSize)
        {
		}

        #endregion //CONSTRUCTORS

        protected void Open()
		{
			if(this.fileStream == null)
			{
				Close();

				if(!File.Exists(this.logFileName))
				{
					CreateNew();
				}

				this.fileStream = new FileStream(this.logFileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
				this.fileStream.Seek(0, SeekOrigin.End);
			}
		}

		protected override void Close()
		{
			if(this.fileStream != null)
			{
				this.fileStream.Close();
				this.fileStream = null;
			}
		}
		
		protected override void WriteToLog(ILogEntry logEntry)
		{
			try
			{
				Open();

				if(this.fileStream.Length >= this.maxSize)
				{
					Close();
					Rename();
					CreateNew();
					Open();
                    CleanupHistory();
				}

				if(this.fileStream != null)
				{
                    if (this.seekToEndBeforeWrite)
                    {
                        this.fileStream.Seek(0, SeekOrigin.End);
                    }

                    Save(logEntry, (Stream)this.fileStream);
					this.fileStream.Flush();
				}
			}
			catch(Exception exception)
			{
				Close();
                Log.AddErrorMessage(exception);
			}            
		}
	}
}
